﻿#pragma once
#include "System.h"
#include "cont/PointLocatorSparseGrid.h"
#include <vtkm/cont/ArrayHandleGroupVecVariable.h>

using ArrayHandleGroupVec = vtkm::cont::ArrayHandleGroupVecVariable<
  vtkm::cont::ArrayHandle<vtkm::Pair<vtkm::Id, vtkm::Vec<vtkm::Int8, 3>>>,
  vtkm::cont::ArrayHandle<vtkm::Id>>;

class LennardJonesSystem : public System
{
public:
  struct InitPositionWorklet;
  struct InitialCondtionWorklet;
  struct ComputeForceWorklet;
  struct ComputeForceWithPeriodicBC;
  struct UpdateVelocityWorklet;
  struct UpdatePositionWorklet;
  struct ComputeNeighborPtsOffsetWorklet;
  struct ComputeNeighborPtsIndexWorklet;

public:
  LennardJonesSystem(const Configuration& cfg);
  virtual ~LennardJonesSystem(){};

  void Init() override;
  void virtual InitialCondition();
  void Evolve() override;

  void ComputeForce();
  void UpdateVelocity();
  void UpdatePosition();


  void virtual TimeIntegration();
  void PreSolve();
  void Solve();
  void PostSolve();

public:
  void InitPointLocator();
  void ComputeNeighborPtsOffset();
  void ComputeNeighborPtsIndex();

protected:
  ArrayHandle<Vec3f> _position;
  ArrayHandle<Vec3f> _force;
  ArrayHandle<Vec3f> _velocity;
  ArrayHandle<Real> _mass;

  Real _rs = 2.5; // 截断距离

  Real _dis;
  std::vector<int> _bin_number;
  vtkm::cont::ArrayHandle<Real> _dis_array;
  SCIAI::cont::PointLocatorSparseGrid _locator;
  ArrayHandleGroupVec _point_ids_array;
  vtkm::cont::Invoker _invoker;
  Real _dt;
  vtkm::Vec<vtkm::Range, 3> _locator_range;
};